from django.utils import timezone
from django.http import HttpResponse
from django.db.models import Q
from rest_framework import status
from rest_framework.viewsets import ViewSet, ReadOnlyModelViewSet
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication

import csv
import datetime
import json
import logging
import tsl_backend.frontend_api.models.order_routing as order_routing
import tsl_backend.frontend_api.models.workorder as workorders
import tsl_backend.users.models as users
import tsl_backend.fgr_api.views.fgr_apis as fgr_apis

import tsl_backend.frontend_api.serializers.report_serializers as report_serializers

from tsl_backend.frontend_api.middleware import response as frontend_response
import tsl_backend.frontend_api.utils.reportView as reportView

import tsl_backend.frontend_api.utils.pagination as table_pagination

class WorkerReportView(ViewSet):
    # http_method_names = ['post']
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]

    @action(detail=False, methods=["post"])
    def get_report_params(self, request):
        """
        Params

        - report_type: handset / transaction

        """
        message = "Success"
        data = {}

        worker_params_serializer = report_serializers.WorkerParamsSerializer(
            data=request.data
        )

        if worker_params_serializer.is_valid():
            report_type = request.data["report_type"]
            staffcode = request.data["staffcode"]
            usercode = request.data["usercode"]
            logging.info(f"queryReportParams for {report_type=}, {staffcode=}, {usercode=}")
            res = fgr_apis.queryReportParams(report_type, staffcode, usercode)
            message = res["message"]
            data = res["data"]

            # logging.info(f"response from queryReportParams: {res}")

            # logging.info(f"return data to frontend: {data}")

        else:
            logging.error(
                f"Fail to get the correct parameters - {request.data}: {worker_params_serializer.errors} "
            )
            message = "Fail to get the correct parameters"

        logging.info(f"Return worker report parameters data to frontend: {data}")
        return frontend_response(status.HTTP_200_OK, message, data)

    @action(detail=False, methods=["post"])
    def get_report_result(self, request):
        """
        Params

        - report_type: handset / transaction
        - date_from: format (2023-01-13T16:39:56)
        - date_to: format (2023-01-13T16:39:56)

        """
        message = "Success"
        data = {}

        logging.info(f"{request.data=}")
        worker_params_serializer = report_serializers.WorkerReportResSerializer(
            data=request.data
        )

        if worker_params_serializer.is_valid():
            report_type = request.data["report_type"]
            staffcode = request.data["staffcode"]
            usercode = request.data["usercode"]
            gold_type = request.data["gold_type"]
            date_from = request.data["date_from"]
            date_to = request.data["date_to"]
            logging.info(f"queryReportResult for {report_type=} {staffcode=} {usercode=} {gold_type=} {date_from=} {date_to=}")
            
            res = fgr_apis.queryReportResult(
                report_type, staffcode, usercode, gold_type, date_from, date_to
            )
            message = res["message"]
            if res["status"] == True:
                data = res["data"]
            else:
                data = {}

            # data = json.loads(return_data.replace("\\",""))
            # logging.info(f"return data to frontend: {data}")

        else:
            logging.error(
                f"Fail to get the correct parameters - {request.data}: {worker_params_serializer.errors} "
            )
            message = "Fail to get the correct parameters"

        logging.info(f"Return worker report result data to frontend: {data}")
        return frontend_response(status.HTTP_200_OK, message, data)
    
    @action(detail=False, methods=["get"])
    def get_report_result_export_csv(self, request):
        """
        工人仓存金报告 / 员工交收报表二(手工帐) / 员工交收查询 导出CSV文件
        Params
        - report_type: 
            handset-员工交收报表二(手工帐)
            transaction-员工交收查询
            storage-工人仓存金报告
        - date_from: format (2023-01-13T16:39:56)
        - date_to: format (2023-01-13T16:39:56)
        """
        data = {}

        logging.info(f"get_report_result_export_csv {request.GET=}")
        worker_params_serializer = report_serializers.WorkerReportResSerializer(data=request.GET)

        if worker_params_serializer.is_valid():
            report_type = request.GET["report_type"]
            staffcode = request.GET["staffcode"]
            usercode = request.GET["usercode"]
            gold_type = request.GET["gold_type"]
            date_from = request.GET["date_from"]
            date_to = request.GET["date_to"]
            logging.info(f"get_report_result_export_csv for {report_type=} {staffcode=} {usercode=} {gold_type=} {date_from=} {date_to=}")
            
            res = fgr_apis.queryReportResult(
                report_type, staffcode, usercode, gold_type, date_from, date_to
            )
            message = res["message"]
            if res["status"] == True:
                data = res["data"]
            else:
                return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "report_type argument should be either 'handset' or 'transaction' or 'storage'",
                    None,
                )
        else:
            logging.error(
                f"Fail to get the correct parameters - {request.data}: {worker_params_serializer.errors} "
            )
            message = "Fail to get the correct parameters"
            return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "report_type argument should be either 'handset' or 'transaction' or 'storage'",
                    None,
                )
        
        # logging.info(f'-------------------------- data:{data}')

        # CSV file header and data fields
        header = ['工人部门', '发出日期', '生产单号', '倒模编号', '金料成色','订单件数', '发出净重', 
                  '石粒数', '石重', '收入日期', '收入净重', '流程给耗', '结存']
        fields = ['wrkdpt', 'out_date', 'sonum', 'designno', 'stkcde', 'qty', 'out_fgwgt', 
                  'stoneqty','stonewgt', 'in_date', 'in_fgwgt', 'scrap', 'fgwgt']

        match report_type:
            case "handset":
                pass
            case "handover":
                header = ['dptcde', 'Crtdate', 'Sonum', 'designnum', 'designno', 'stkcde', 'qty_order', 
                  'Qty_orderVhr','Remark2', 'StoneItm', 'TinQty', 'TotQty', 'AddGoldQty', 'FGStoneQty', 'NKDesc',
                  'Noitm_order', 'Scrape', 'Unit_cost', 'Var_tax', 'method', 'vhrnum']
                fields = ['dptcde', 'Crtdate', 'Sonum', 'designnum', 'designno', 'stkcde', 'qty_order', 
                  'Qty_orderVhr','Remark2', 'StoneItm', 'TinQty', 'TotQty', 'AddGoldQty', 'FGStoneQty', 'NKDesc',
                  'Noitm_order', 'Scrape', 'Unit_cost', 'Var_tax', 'method', 'vhrnum']
            case "transaction":
                header = ['工人部门', '发出日期', '生产单号', '倒模编号', '金料成色','订单件数', '发出净重', 
                  '石粒数', '石重', '收入日期', '收入净重', '流程给耗', '结存', '核实签名']
                fields = ['wrkdpt', 'out_date', 'sonum', 'designno', 'stkcde', 'qty', 'out_fgwgt', 
                  'stoneqty','stonewgt', 'in_date', 'in_fgwgt', 'scrap', 'fgwgt', 'check_sgin']
            case "storage":
                pass               
            case _:
                return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "report_type argument should be either 'handset' or 'transaction'",
                    None,
                )

        # CSV file name     
        now = timezone.now().strftime('%Y%m%dT%H%M%S')
        filename = '"data_{}.csv"'.format(now)
        logging.info(f'get_report_result_export_csv filename={filename}')

        # to JSON object
        data2 = json.loads(data)
        # writer CSV data to reponse
        response = export_data_to_csv(data2['data'], header, fields, filename, number_row_operator)
        logging.info(f"get_report_result_export_csv end")
        return response

    @action(detail=False, methods=["post"])
    def testInventory(self, request):
        account_id = request.POST.get("account_id", None)
        account = users.Account.objects.get(pk=account_id)

        received_at = request.POST.get("received_at", None)
        checked_at = request.POST.get("checked_at", None)
        site = request.POST.get("site", None)
        workorder = request.POST.get("workorder", None)
        department = request.POST.get("department", None)
        worker_name = request.POST.get("worker_name", None)
        checker_name = request.POST.get("checker_name", None)

        input_data = [
            {
                "received_at": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).qc_check.received_at.strftime("%d/%m/%Y"),
                "checked_at": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).qc_check.check_at.strftime("%d/%m/%Y"),
                "site": routing.workorder.site.name if routing.workorder.site else None,
                "workorder": routing.workorder.order,
                "design": routing.workorder.design,
                "gold_type": routing.workorder.gold_type,
                "quantity": routing.workorder.quantity,
                "total_count": routing.workorder.total_count,
                "pass_count": routing.workorder.quantity,  # being changed in below
                "failed": [
                    {
                        "reason": failed_detail.reason.reason,
                        "quantity": failed_detail.quantity,
                        "unit": failed_detail.reason.unit,
                    }
                    for failed_detail in order_routing.Record.objects.get(
                        route_detail_id=order_routing.RouteDetail.objects.get(
                            order_route_id=routing, flow_id=account.department.flow
                        )
                    ).qc_check.failed_details.all()
                ],
                "department": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).worker.account.department.name,
                "worker_code": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).worker.account.user_code,
                "worker_name": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).worker.account.django_user.cnName,
                "checker_code": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).qc_check.account.user_code,
                "checker_name": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).qc_check.account.django_user.cnName,
                "checker_role": order_routing.Record.objects.get(
                    route_detail_id=order_routing.RouteDetail.objects.get(
                        order_route_id=routing, flow_id=account.department.flow
                    )
                ).qc_check.account.role.name,
            }
            for routing in getOrderRoutings(account)
        ]

        output_data = []
        for input_dict in input_data:
            for failed in input_dict["failed"]:
                output_dict = input_dict.copy()
                output_dict["failed"] = failed
                if len(output_dict["failed"]) > 0:
                    output_dict["pass_count"] -= 1
                output_data.append(output_dict)

        # filter (received_at, checked_at, site, workorder, department, worker_name, checker_name)
        if received_at is not None:
            output_data = filter(lambda x: x["received_at"] == received_at, output_data)
        if checked_at is not None:
            output_data = filter(lambda x: x["checked_at"] == checked_at, output_data)
        if site is not None:
            output_data = filter(lambda x: x["site"] == site, output_data)
        if workorder is not None:
            output_data = filter(lambda x: x["workorder"] == workorder, output_data)
        if department is not None:
            output_data = filter(lambda x: x["department"] == department, output_data)
        if worker_name is not None:
            output_data = filter(lambda x: x["worker_name"] == worker_name, output_data)
        if checker_name is not None:
            output_data = filter(
                lambda x: x["checker_name"] == checker_name, output_data
            )

        return frontend_response(status.HTTP_200_OK, "", output_data)

    @action(detail=False, methods=["post"])
    def leadtime(self, request):
        account_id = request.POST.get("account_id", None)
        account = users.Account.objects.get(pk=account_id)

        fgr_num = request.POST.get("fgr_num", None)
        site = request.POST.get("site", None)
        flow = request.POST.get("flow", None)
        dept11 = request.POST.get("dept11", None)

        if flow is None:
            return frontend_response(
                status.HTTP_400_BAD_REQUEST, "Missing flow parameter", []
            )

        data = [
            {
                "site": routing.workorder.site.name if routing.workorder.site else None,
                "fgr_num": routing.workorder.order,
                "order_type": "",
                "order_date": "",
                "due_date": routing.workorder.due_date.strftime("%d/%m/%Y"),
                "due_month": "overdue"
                if routing.workorder.due_date < timezone.now()
                else None,
                "design": routing.workorder.design,
                "po_no": "",
                "stone_item": "",  # TODO: none
                "po_desc": "",
                "goods_type": routing.workorder.goods_type,
                "catcde": "",  # TODO: none
                "order_quantity": routing.workorder.quantity,
                "dept1": "",  # TODO: none
                "dept11": "",  # TODO: none
                "datfrm1": "",  # TODO: none
                "dept3": "",  # TODO: none
                "dept31": "",  # TODO: none
                "stpdays": "",  # TODO: none
                "dept4": "",  # TODO: none
                "datfrm4": "",  # TODO: none
                "gldcde": "",  # TODO: none
                "complete_date": order_routing.RouteDetail.objects.get(
                    order_route_id=routing, flow_id=flow
                ).dispatcher.end_at,
                "overdue": "",  # TODO: none
                "pf_num": "",  # TODO: none
                "deptr": "",  # TODO: none
                "ring_type": routing.workorder.ring_type,
                "ready_date": routing.workorder.ready_date,
                "product_cde": routing.workorder.master.fg_article,
                "sales_mix": "",  # TODO: none
                "product_mix": "",  # TODO: none
                "mould": routing.workorder.mould,
                "sbu_date": "",  # TODO: none
                "podesc2": "",  # TODO: none
                "order_type2": "",  # TODO: none
                "flow": order_routing.RouteDetail.objects.get(
                    order_route=routing, flow_id=flow
                ).flow.name,
                "role": "",  # TODO: none
                "worker_code": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .worker.account.user_code,
                "worker_name": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .worker.account.django_user.cnName,
                "worker_counter": order_routing.WorkerActionRecord.objects.filter(
                    worker_record=order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .worker
                ).count(),
                "worker_start": order_routing.WorkerActionRecord.objects.filter(
                    worker_record=order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .worker,
                    action=1,
                )
                .first()
                .time,
                "worker_pause": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .worker.pause_duration,
                "worker_finish": order_routing.WorkerActionRecord.objects.filter(
                    worker_record=order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .worker,
                    action=3,
                )
                .last()
                .time,
                "worker_duration_a": str(
                    order_routing.WorkerActionRecord.objects.filter(
                        worker_record=order_routing.Record.objects.filter(
                            route_detail=order_routing.RouteDetail.objects.get(
                                order_route=routing, flow_id=flow
                            )
                        )
                        .last()
                        .worker,
                        action=3,
                    )
                    .last()
                    .time
                    - order_routing.WorkerActionRecord.objects.filter(
                        worker_record=order_routing.Record.objects.filter(
                            route_detail=order_routing.RouteDetail.objects.get(
                                order_route=routing, flow_id=flow
                            )
                        )
                        .last()
                        .worker,
                        action=1,
                    )
                    .first()
                    .time
                ),
                "worker_duration_b": str(
                    order_routing.WorkerActionRecord.objects.filter(
                        worker_record=order_routing.Record.objects.filter(
                            route_detail=order_routing.RouteDetail.objects.get(
                                order_route=routing, flow_id=flow
                            )
                        )
                        .last()
                        .worker,
                        action=3,
                    )
                    .last()
                    .time
                    - order_routing.WorkerActionRecord.objects.filter(
                        worker_record=order_routing.Record.objects.filter(
                            route_detail=order_routing.RouteDetail.objects.get(
                                order_route=routing, flow_id=flow
                            )
                        )
                        .last()
                        .worker,
                        action=1,
                    )
                    .first()
                    .time
                    - order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .worker.pause_duration
                ),
                "qc_code": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .qc_check.account.user_code,
                "qc_name": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .qc_check.account.django_user.cnName,
                "qc_counter": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    ),
                    qc_check__isnull=False,
                ),
                "qc_start": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .first()
                .qc_check.check_at,
                "qc_finish": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .qc_check.check_at,
                "qc_duration_a": str(
                    order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .qc_check.check_at
                    - order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .first()
                    .qc_check.check_at
                ),
                "leader_code": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .leader_check.account.user_code,
                "leader_name": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .leader_check.account.django_user.cnName,
                "leader_counter": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    ),
                    leader_check__isnull=False,
                ),
                "leader_start": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .first()
                .leader_check.check_at,
                "leader_finish": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .leader_check.check_at,
                "leader_duration_a": str(
                    order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .leader_check.check_at
                    - order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .first()
                    .leader_check.check_at
                ),
                "stone_code": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .stone_check.account.user_code,
                "stone_name": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .stone_check.account.django_user.cnName,
                "stone_counter": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    ),
                    stone_check__isnull=False,
                ),
                "stone_start": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .first()
                .stone_check.check_at,
                "stone_finish": order_routing.Record.objects.filter(
                    route_detail=order_routing.RouteDetail.objects.get(
                        order_route=routing, flow_id=flow
                    )
                )
                .last()
                .stone_check.check_at,
                "stone_duration_a": str(
                    order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .last()
                    .stone_check.check_at
                    - order_routing.Record.objects.filter(
                        route_detail=order_routing.RouteDetail.objects.get(
                            order_route=routing, flow_id=flow
                        )
                    )
                    .first()
                    .stone_check.check_at
                ),
                "dispatcher_start": order_routing.RouteDetail.objects.get(
                    order_route_id=routing, flow_id=flow
                ).dispatcher.start_at,
            }
            for routing in getOrderRoutings(account)
        ]

        # filter (fgr_num, site, dept11)
        if fgr_num is not None:
            data = filter(lambda x: x["fgr_num"] == fgr_num, data)
        if site is not None:
            data = filter(lambda x: x["site"] == site, data)
        if dept11 is not None:
            data = filter(lambda x: x["dept11"] == dept11, data)

        return frontend_response(status.HTTP_200_OK, "", data)


class QCInventoryReportView(ReadOnlyModelViewSet):

    # queryset = order_routing.Record.objects.all().select_related("worker", "worker__account", "qc_check", "leader_check", "stone_check", "route_detail", "route_detail__order_route")

    # http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    # transaction_serializer_class = report_serializers.QCTransactionSerializer
    # pagination_class = table_pagination.ResultsSetPagination
    
    @action(detail=False, methods=["post"])
    def qcInventory(self, request):
        """
        实时存货报表
        Params

        - report_type: handset / transaction

        """
        report_type = request.POST.get("report_type", None)
        account_id = request.POST.get("account_id", None)

        logging.info(f"{request.POST}")

        match report_type:
            case "handset":
                data = real_time_inventory_report_handset(users.Account.objects.get(pk=account_id))
            case "transaction":
                # data = transaction(users.Account.objects.get(pk=account_id))
                data = []
            case _:
                return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "report_type argument should be either 'handset' or 'transaction'",
                    None,
                )
        
        group_by, summary = group_by_name(data)

        content = {
            "data": data,
            "group_by": group_by,
            "summary": summary
        }
        return frontend_response(status.HTTP_200_OK, "", content)
    
    @action(detail=False, methods=["get"])
    def qcInventoryExportCsv(self, request):
        """
        实时存货报表导出
        Params
        - report_type: handset / transaction
        """

        logging.info(f"检测货品交易报表导出CSV req:{request.GET}")
        report_type = request.query_params.get("report_type", None)
        account_id = request.query_params.get("account_id", None)

        match report_type:
            case "handset":
                data = real_time_inventory_report_handset(users.Account.objects.get(pk=account_id))
            case "transaction":
                # data = transaction(users.Account.objects.get(pk=account_id))
                data = []
            case _:
                return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "report_type argument should be either 'handset' or 'transaction'",
                    None,
                )

        # CSV file header and data fields
        header = ['收货日期', '地点', '生产单号', '货单交货期', '设计编号','成色', '件数', 
                  '部门名称', '工人编号', '工人姓名', '检测员编号', '检测员姓名', '检测员身份']
        fields = ['received_date', 'source', 'workorder', 'due_date', 'design', 'gold_type', 'quantity', 
                  'worker__department','worker__code', 'worker__name', 'checker__code', 'checker__name', 'checker__role']

        # CSV file name
        now = timezone.now().strftime('%Y%m%dT%H%M%S')
        filename = '"data_{}.csv"'.format(now)
        logging.info(f'qcInventoryExportCsv filename={filename}')
        
        # write CSV data to response
        response = qc_inventory_export_data_to_csv(data, header, fields, filename)
        logging.info(f"检测货品交易报表导出CSV end")
        return response
    

class QCReportView(ReadOnlyModelViewSet):
    
    queryset = order_routing.Record.objects.all().select_related("worker", "worker__account", "qc_check", "leader_check", "stone_check", "route_detail", "route_detail__order_route")

    # http_method_names = ["post"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    transaction_serializer_class = report_serializers.QCTransactionSerializer
    pagination_class = table_pagination.ResultsSetPagination
    
    @action(detail=False, methods=["post"])
    def qcTransactionReport(self, request):
        # 检测货品交易报表
        message="Success"
        data=[]
        # sort_seq=request.POST.get("sort_seq", "route_detail__order_route__workorder__order")
        sort_seq=request.POST.get("sort_seq", "route_detail__order_route__workorder__order")

        logging.info(f"Get QC transaction report: {request.data}")
        transaction_serializer = self.transaction_serializer_class(data=request.data)

        if transaction_serializer.is_valid():
            record_objs, account_obj = transaction_serializer.filter_record(self.queryset)
            sorted_record_objs = table_pagination.transaction_sorting(record_objs, sort_seq)
            # logging.info(f"{sorted_record_objs=}")

            # Pagination
            paginated_data = transaction_serializer.parse_data(sorted_record_objs, account_obj)
            page_record_objs = self.paginate_queryset(paginated_data)

            # Generate paginated response
            paginated_response = self.get_paginated_response(page_record_objs)
            # logging.info(f"{paginated_response=}")
            data = paginated_response.data  
            # logging.info(f"{data=}")
        else:
            logging.error(
                f"Fail to get the correct parameters - {request.data}: {transaction_serializer.errors} "
            )
            message = "Fail to get the record for QC transaction report"
            paginated_data = []
            paginated_response = self.get_paginated_response(paginated_data)
            data = paginated_response.data  

        return frontend_response(status.HTTP_200_OK, message, data)
    
    @action(detail=False, methods=["get"])
    def qcTransactionExportCsv(self, request):
        # 检测货品交易报表导出CSV
        logging.info(f"检测货品交易报表导出CSV start req: {request.GET}")
        transaction_serializer = self.transaction_serializer_class(data=request.GET)
        data=[]

        if transaction_serializer.is_valid():
            record_objs, account_obj = transaction_serializer.filter_record(self.queryset)
            data = transaction_serializer.parse_data(record_objs, account_obj)
            new_data = transaction_serializer.filter_csv_data(data)
        else:
            logging.error(
                f"Fail to get the correct parameters - {request.GET}: {transaction_serializer.errors} "
            )
            message = "Fail to get the record for QC transaction report"
            return frontend_response(
                    status.HTTP_400_BAD_REQUEST,
                    "Fail to get the record for QC transaction report",
                    None,
                )

        # CSV file header and data fields
        header = ['收货日期', '完成检测日期', '地点', '生产单号', '设计编号','成色', '件数', 
                  '石粒数', '合格件数', '不合格件数', '不合格原因', '不合格数量', '不合格数量单位',
                  '部门名称', '工人编号', '工人姓名', '检测员编号', '检测员姓名', '检测员身份']
        fields = ['deliverDate', 'completeDate', 'source', 'orderNo', 'designNum', 'goldType', 'qty', 
                  'stoneQty', 'passQty', 'unqualified_num', 'failReason__reason', 'failReason__failQty', 'failReason__failUnit', 
                  'dept', 'workerCode', 'workerName', 'checkerCode', 'checkerName', 'checkerRole']

        # CSV file name
        now = timezone.now().strftime('%Y%m%dT%H%M%S')
        filename = '"data_{}.csv"'.format(now)
        logging.info(f'qcInventoryExportCsv filename={filename}')
        
        response = HttpResponse(content_type='text/csv')
        'attachment; filename="{}"'.format(filename)
        response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)
        writer = csv.writer(response)
        writer.writerow(header)  # 写入标题行
        for obj in new_data:
            row = (str(obj[field]) if obj[field] is not None else "" for field in fields)
            writer.writerow(row)

        logging.info(f"检测货品交易报表导出CSV end ")
        return response
    
class PrintStatusReportView(ReadOnlyModelViewSet):

    queryset = workorders.Detail.objects.all().select_related("site", "master").order_by("order")

    # http_method_names = ["get"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    print_status_serializer_class = report_serializers.PrintStatusSerializer
    pagination_class = table_pagination.ResultsSetPagination

    def list(self, request):
        logging.info(f"Query for print status report")
        logging.info(f"Reuqest from user: {request.GET}")

        data=[]

        gold_print_status = request.GET.get("gold_print_status", "all")   # printed/notPrint/all
        if gold_print_status=="printed":
            detail_objs = self.queryset.filter(gold_print_date__isnull=False)
        elif gold_print_status=="notPrint":
            detail_objs = self.queryset.filter(gold_print_date__isnull=True)
        else:
            detail_objs = self.queryset

        sort_seq=request.GET.get("sort_seq", "order")

        if detail_objs:
            sort_detail_objs = table_pagination.print_status_sorting(detail_objs, sort_seq)

            page_detail_objs = self.paginate_queryset(sort_detail_objs)
            serializer = self.print_status_serializer_class(page_detail_objs, many=True)

        else:
            page_detail_objs=None

        if page_detail_objs is not None:
            logging.info(f"Print report record: {page_detail_objs}")
            paginated_response = self.get_paginated_response(serializer.data)
            data = paginated_response.data  
            data["results"] = self.print_status_serializer_class().update_order(data["results"])

        else:
            logging.info(f"No print report record: {page_detail_objs}")
            data = serializer.data

        logging.info(f"Print status report data: {data}")

        message = "Success"
        return frontend_response(status.HTTP_200_OK, message, data)

    @action(detail=False, methods=["get"])
    def list_export_csv(self, request):
        """
            生产单标签打印状况报表导出CSV文件
            params
                gold_print_status: all-全部, notPrint-未打标签日期, printed-已打标签日期
        """
        logging.info(f"PrintStatusReportExportCsv req: {request.GET}")

        gold_print_status = request.GET.get("gold_print_status", "all")
        if gold_print_status=="printed":
            detail_objs = self.queryset.filter(gold_print_date__isnull = False)
        elif gold_print_status=="notPrint":
            detail_objs = self.queryset.filter(gold_print_date__isnull = True)
        else:
            detail_objs = self.queryset

        sort_seq = request.GET.get("sort_seq", "order")
        sort_detail_objs = detail_objs.order_by(sort_seq)

        serializer = self.print_status_serializer_class(sort_detail_objs, many=True)
        data = self.print_status_serializer_class().update_order(serializer.data)
        logging.info(f"Print status report data type: {type(data)}")

        # CSV file header and data fields
        header = ['地点', 'FGRNUM', 'ORDERTYPE', 'ORDDATE', 'DUEDAT','DESIGN', 'PONO', 'PODESC', 'TYPCDE', 'ORDQTY',
                   'DEPT1', 'DEPT11', 'DATFRM1', 'GLDCDE', 'DEPTR', 'RING_TYPE', 'PRODUCTCDE', 'MOULDNO', 'SBUDATE', '金仓打印日期', '石仓打印日期']
        fields = ['source', 'fgNum', 'orderType', 'orddate', 'duedat', 'design', 'order', 'podesc','goods_type', 'quantity',
                   'dept1', 'dept11', 'datfrm1', 'gldcde', 'deptr', 'ring_type', 'productcde', 'mould', 'sbu_date', 'gold_print_date', 'stone_print_date']
       
        # CSV file name
        now = timezone.now().strftime('%Y%m%dT%H%M%S')
        filename = '"data_{}.csv"'.format(now)
        logging.info(f'PrintStatusReportExportCsv filename={filename}')

        # write CSV data to response
        response = export_data_to_csv(data, header, fields, filename)
        logging.info(f"PrintStatusReportExportCsv end")
        return response

class LeadTimeReportView(ReadOnlyModelViewSet):

    queryset = workorders.Detail.objects.all().select_related("site", "master")

    http_method_names = ["get"]
    permission_classes = [IsAuthenticated]
    authentication_classes = [JWTAuthentication]
    # leadtime_serializer_class = report_serializers.LeadTimeSerializer
    pagination_class = table_pagination.ResultsSetPagination
    
    def list(self, request):
        logging.info(f"Query for leadtime report")
        logging.info(f"Reuqest from user: {request.GET}")
        
        account_id = request.GET.get("account_id", None)
        source = request.GET.get("source", None)
        order = request.GET.get("order_no", None)

        flow = request.GET.get("flow", None)
        dept = request.GET.get("dept", None)
        # sort_seq=request.GET.get("sort_seq", "order_route__workorder__order")
        sort_seq=request.GET.get("sort_seq", "site")
        
        route_detail_objs = reportView.filter_leadtime_objs(account_id, source, order, flow, dept)

        if route_detail_objs:
            sorted_route_detail_objs = table_pagination.leadtime_sorting(route_detail_objs, sort_seq)
            page_detail_objs = self.paginate_queryset(sorted_route_detail_objs)
            paginated_data = reportView.parse_leadtime_data(page_detail_objs, sort_seq)
            paginated_response = self.get_paginated_response(paginated_data)
            data = paginated_response.data  
        else:
            logging.info(f"No leadtime report record: {route_detail_objs}")
            paginated_data = []
            paginated_data = self.paginate_queryset(paginated_data) # 初始化-分页
            paginated_response = self.get_paginated_response(paginated_data)
            data = paginated_response.data  
            
        message = "Success"
        return frontend_response(status.HTTP_200_OK, message, data)

    @action(detail=False, methods=["get"])
    def get_option_list(self, request):
        data={}
        site_objs = users.Site.objects.all()
        flow_objs = users.Flow.objects.all()
        dept_objs = users.Department.objects.all()

        site_serializer = report_serializers.SiteSerializer(site_objs, many=True)
        site_data=site_serializer.data

        flow_serializer = report_serializers.FlowSerializer(flow_objs, many=True)
        flow_data=flow_serializer.data

        dept_serializer = report_serializers.DepartmentSerializer(dept_objs, many=True)
        dept_data=dept_serializer.data

        data["dept_data"]=dept_data
        data["flow_data"]=flow_data
        data["site_data"]=site_data

        message = "Success"
        return frontend_response(status.HTTP_200_OK, message, data)

    @action(detail=False, methods=["get"])
    def list_export_csv(self, request):
        """
            各工序节点Leadtime报表导出CSV文件
            params
                site: 购货单位
                order_no: 生产单号
                flow: 工艺节点
                dept: 部门名称
        """
        logging.info(f"export leadtime report req: {request.GET}")
        
        account_id = request.GET.get("account_id", None)
        source = request.GET.get("source", None)
        order = request.GET.get("order_no", None)
        flow = request.GET.get("flow", None)
        dept = request.GET.get("dept", None)

        # 原来数据
        # data = reportView.parse_leadtime_data_4_export(account_id, site, order, flow, dept)

        # 查询数据相同
        route_detail_objs = reportView.filter_leadtime_objs(account_id, source, order, flow, dept)
        data = reportView.parse_leadtime_csv_data(route_detail_objs)

        logging.info(f'--------------- list_export_csv data:{data}')

         # CSV file header and data fields
        header = ['地点', 'FGRNUM', 'ORDERTYPE', 'ORDDATE', 'DUEDAT','DUEMONTH', 'DESIGN', 'PONO', 'STONEITM', 'PODESC',
                  'GOODSTYPE', 'CATCDE', 'ORDQTY', 'DEPT1 ', 'DEPT11','DATFRM1', 'DEPT3', 'DEPT31', 'STPDAYS', 'DEPT4',
                  'DATFRM4', 'GLDCDE', 'COMPLET', 'OVERDUE', 'PFNUM', 'DEPTR', 'RING_TYPE', 'READYDATE', 'PRODUCTCDE', 'SALES_MIX',
                  'PRDUCT_MIX', 'MOULDNO', 'SBUDATE', 'PODESC2', 'ORDER_TYPE', '工艺节点', '生产节点', '工人编码', '工人姓名', 'WORKER COUNTER',
                  '工人开始日期/时间', '工人暂停时间合计(时)', '工人完成日期/时间', '工時A', '工時B', 'QC编码', 'QC姓名', 'QC开始日期/时间', 'QC完成日期/时间', '工時A',
                  '组长编码', '组长姓名', '组长开始日期/时间', '组长完成日期/时间', '工時A', '验石员编码', '验石员姓名', '验石员开始日期/时间', '验石员完成日期/时间', '工時A',
                  'FGR收发收货日期/时间',]
        fields = ['source', 'fgNum', 'orderType', 'orddate', 'duedat', 'dueMonth', 'designNum', 'pono', 'stoneItem', 'podesc',
                  'goods_type', 'catcde', 'ordqty', 'dept1', 'dept11', 'datfrm1', 'dept3', 'dept31', 'stpdays', 'dept4',
                  'datfrm4', 'gldcde', 'complet', 'overdue', 'pfnum', 'deptr', 'ringType', 'readyDate', 'productcde', 'salesMix',
                  'productMix', 'mouldNo', 'sbudate', 'podesc2', 'orderType2', 'flow', 'role', 'worker_code', 'worker_name', 'worker_counter', 
                  'worker_start', 'worker_pause', 'worker_finish', 'worker_duration_a', 'worker_duration_b', 'qc_code', 'qc_name', 'qc_start', 'qc_finish', 'qc_duration_a',
                  'leader_code', 'leader_name', 'leader_start', 'leader_finish', 'leader_duration_a', 'stone_code', 'stone_name', 'stone_start', 'stone_finish', 'stone_duration_a',
                  'dispatcher_start',]
        
        # CSV file name
        now = timezone.now().strftime('%Y%m%dT%H%M%S')
        filename = '"leadtime_{}.csv"'.format(now)
        logging.info(f'leadtime filename={filename}')
        # logging.info(f'-------------------------- leadtime data={data}')

        # write CSV data to reponse
        response = export_data_to_csv(data, header, fields, filename)
        logging.info(f"export leadtime report req end")
        return response 

def real_time_inventory_report_get_order_routings(account):
    # 只获取检测岗位(就是不要工人)
    query = order_routing.OrderRouting.objects.exclude(holder__role__name="WORKER")
    match account.role.name:
        case "CenterSender" | "Teamleader":
            # 收发/组长(看当前部门内的)
            return query.filter(holder__department=account.department).order_by("workorder__order")
        case "Master":
            # 管理
            return query.filter(holder__isnull=False).order_by("workorder__order")
        case "QC" | "StoneQC":
            # QC/验石员
            return query.filter(holder_id=account).order_by("workorder__order")
        case _:
            # 金倉/default
            return []

def getOrderRoutings(account):
    match account.role.name:
        # case "WORKER":
        #     # TEST
        #     return order_routing.OrderRouting.objects.all()
        case "Master" | "CenterSender":
            # 管理/收发
            return order_routing.OrderRouting.objects.filter(holder__department=account.department).order_by("workorder__order")
        case "QC" | "StoneQC":
            # QC/验石员
            return order_routing.OrderRouting.objects.filter(holder_id=account).order_by("workorder__order")
        case "Teamleader":
            # 组长
            account_ids = users.Account.objects.filter(user_code=account.user_code, role__name__in=["QC" , "StoneQC"]).values_list("id", flat=True)
            return order_routing.OrderRouting.objects.filter(holder_id__in=account_ids).order_by("workorder__order")
        case _:
            # 金倉/default
            return []


def compare_dict_values(dict1, dict2):
    return all(value == dict2.get(key) for key, value in dict1.items())


def remove_unique_dict(input_list):
    dict_count = {}
    for input_dict in input_list:
        dict_count[str(input_dict)] = dict_count.get(str(input_dict), 0) + 1
    for input_dict in input_list[:]:
        if dict_count[str(input_dict)] == 1:
            input_list.remove(input_dict)


def combine_duplicate_dict(input_list):
    dict_count = {}
    for input_dict in input_list:
        dict_count[str(input_dict)] = dict_count.get(str(input_dict), 0) + 1
    combined_dict = {}
    for input_dict in input_list:
        if dict_count[str(input_dict)] > 1:
            for key, value in input_dict.items():
                combined_dict[key] = combined_dict.get(key, []) + [value]
    return combined_dict

def qcTransaction_row_operator(row):
    if len(row) > 9 and row[6]:
        if row[8]:
            row[9] = row[6] - row[8]
        else:
            row[9] = row[6]

def default_row_operator(row):
    pass

def export_data_to_csv(data, header, fields, filename, callbackrow = default_row_operator):
    response = HttpResponse(content_type='text/csv')
    # response.charset = 'utf-8-sig' if 'Windows' in request.headers.get('User-agent') else 'utf-8'
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)

    writer = csv.writer(response)
    writer.writerow(header)
    
    # Write the data rows
    for obj in data:
        row = [nested_dictitem(obj, field) for field in fields]
        # logging.info(f'----------  row:{row}')
        callbackrow(row)
        # logging.info(f'---------- row-:{row}')
        writer.writerow(row)

    return response

def qc_inventory_export_data_to_csv(data, header, fields, filename, callbackrow = default_row_operator):
    response = HttpResponse(content_type='text/csv')
    # response.charset = 'utf-8-sig' if 'Windows' in request.headers.get('User-agent') else 'utf-8'
    response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename)

    writer = csv.writer(response)
    writer.writerow(header)
    
    # Write the data rows
    for obj in data:
        row = [qc_inventory_export_csv_nested_dictitem(obj, field) for field in fields]
        # logging.info(f'----------  row:{row}')
        callbackrow(row)
        # logging.info(f'---------- row-:{row}')
        writer.writerow(row)

    return response

def qc_inventory_export_csv_nested_dictitem(obj, attribute, split_rule='__'):
    """
    This function is responsible for getting the nested record from the given obj parameter
    :param obj: whole item without splitting
    :param attribute: field after splitting
    :param split_rule:
    :return:
    """
    split_attr = attribute.split(split_rule)
    level = len(split_attr) 
    if obj:
        objVal = obj.get(split_attr[0])
        if not objVal is None:
            if level == 1:
                if is_date(objVal):
                    return objVal.strftime('%Y-%m-%d')
                return objVal
            elif level == 2:
                if len(objVal) > 0:
                    if split_attr[0] == "worker":
                        if len(objVal) >=2 and objVal[-1].get(split_attr[1]) == "":
                            objVal2 = objVal[-2].get(split_attr[1]) 
                        else:
                            objVal2 = objVal[-1].get(split_attr[1])
                    else:
                        objVal2 = objVal[0].get(split_attr[1]) 
                    if not objVal2 is None:
                        if is_date(objVal2):
                            return objVal2.strftime('%Y-%m-%d')
                        return objVal2
            else:
                logging.error(f'nested_dictitem not sport level:{level}') 

    return ''


def nested_dictitem(obj, attribute, split_rule='__'):
    """
    This function is responsible for getting the nested record from the given obj parameter
    :param obj: whole item without splitting
    :param attribute: field after splitting
    :param split_rule:
    :return:
    """
    split_attr = attribute.split(split_rule)
    level = len(split_attr) 
    if obj:
        objVal = obj.get(split_attr[0])
        if not objVal is None:
            if level == 1:
                if is_date(objVal):
                    return objVal.strftime('%Y-%m-%d')
                return objVal
            elif level == 2:
                if len(objVal) > 0:
                    objVal2 = objVal[0].get(split_attr[1]) 
                    if not objVal2 is None:
                        if is_date(objVal2):
                            return objVal2.strftime('%Y-%m-%d')
                        return objVal2
            else:
                logging.error(f'nested_dictitem not sport level:{level}') 

    return ''

def is_date(date):
    return isinstance(date, datetime.date)

def number_row_operator(row) -> str:
    """
    浮点数保留3位小数
    :param data
    """
    for index, data in enumerate(row):
        s = str(data)
        if s.isdigit():
            if len(s.split("."))==2:
                row[index] =  str(round(s, 3))
            row[index] =  s + "\t"

def group_by_name(data):
    group_by_schema = {
        "role_chinese_name": "QC",
        "cnName": "",
        "deptName": "",
        "children": []
        }
    children_schema = {
        "worker": "",
        "orderQty": 0,
        "quantity": 0
    }
    summary = {
        "quantity_count":0,
        "order_qty_count":0
    }
    group_by_data_dict = {}
    children_dict = {}
    try:
        for obj in data:
            checker_len = len(obj["checker"]) - 1
            cn_name = obj["checker"][checker_len]["role"]
            if cn_name and cn_name not in group_by_data_dict:
                copy_dict = group_by_schema.copy()
                copy_dict["cnName"] = obj["checker"][checker_len]["name"]
                copy_dict["role_chinese_name"] = obj["checker"][checker_len]["role"]

                copy_dict["deptName"] = obj["worker"][0]["department"]
                group_by_data_dict[cn_name] = copy_dict
            
            if obj["checker"][checker_len]["name"] not in copy_dict["cnName"]:
                copy_dict["cnName"] = copy_dict["cnName"] + "/" + obj["checker"][checker_len]["name"]

            work_name = obj["worker"][0]["name"]
            if work_name not in children_dict.setdefault(cn_name, {}):
                children_dict[cn_name][work_name] = children_schema.copy()
            
            children_dict[cn_name][work_name]["worker"] = work_name
            children_dict[cn_name][work_name]["orderQty"] += 1
            children_dict[cn_name][work_name]["quantity"] += obj["quantity"]

            if cn_name:
                summary["quantity_count"] += obj["quantity"]
                summary["order_qty_count"] += 1

        for cn_name in group_by_data_dict:
            group_by_data_dict[cn_name]["children"] = list(children_dict[cn_name].values())
        
        return list(group_by_data_dict.values()), summary

    except Exception as e:
        logging.info(f"group_data: {data}")
        logging.error(e)
        return [], 0


def check_is_failed_details(record:order_routing.Record):
    fail = record.qc_check.failed_details.all()
    if fail:
        return True
    return False


def check_record_is_process(records: list[order_routing.Record]):
    for record in records:
        # 检查 QC 检查
        qc_check_valid = (
            record.qc_check and 
            record.qc_check.account and 
            record.qc_check.account.django_user.cnName and 
            record.qc_check.check_at is None
        )
        
        # 检查 Leader 检查
        leader_check_valid = (
            record.leader_check and 
            record.leader_check.account and 
            record.leader_check.account.django_user.cnName and 
            record.leader_check.check_at is None
        )
        
        # 检查 Stone 检查
        stone_check_valid = (
            record.stone_check and 
            record.stone_check.account and 
            record.stone_check.account.django_user.cnName and 
            record.stone_check.check_at is None
        )
        
        # 如果任何一个检查条件有效，将记录加入到结果中
        if qc_check_valid or leader_check_valid or stone_check_valid:
            return True
    return False


def get_checker_data(routing: order_routing.OrderRouting, is_process: bool):
    if is_process:
        return {
            "code": "",
            "name": "",
            "role": ""
        }

    return {
        "code": routing.holder.user_code if routing.holder else '',
        "name": routing.holder.django_user.cnName if routing.holder else '',
        "role": routing.holder.role.chinese_name if routing.holder else '',
    }       


def real_time_inventory_report_handset(account):
    """实时存货报表-获取数据"""
    # 获取订单路线
    order_routings = real_time_inventory_report_get_order_routings(account)
    
    result = []

    # 主管获取全部
    route_detail_query = Q()
    # 空的去除掉
    records_query = Q(Q(worker__isnull=False)|Q(leader_check__isnull=False)|Q(stone_check__isnull=False))
    if "PMC" not in account.department.name:
        route_detail_query &= Q(flow_id=account.department.flow)
    
    for routing in order_routings:
        # 获取记录列表
        records = order_routing.Record.objects.filter(
            route_detail__in=order_routing.RouteDetail.objects.filter(
                order_route_id=routing, 
            ).filter(route_detail_query)
        ).filter(records_query)

        # is_process = check_record_is_process(records)
        
        # 构造每个路由的字典
        routing_data = {
            "received_date": routing.holder_record_time,
            "site": routing.workorder.site.name if routing.workorder.site else None,
            "source": routing.workorder.source or None,
            "workorder": routing.workorder.order,
            "due_date": routing.workorder.due_date,
            "design": routing.workorder.design,
            "gold_type": routing.workorder.gold_type,
            "quantity": routing.workorder.quantity,
            "worker": [
                {
                    "department": record.worker.account.department.name if record.worker and record.worker.account else '',
                    "code": record.worker.account.user_code if record.worker and record.worker.account else '',
                    "name": record.worker.account.django_user.cnName if record.worker and record.worker.account else '',
                    # "fail": check_is_failed_details(record),
                }
                for record in records 
            ],
            "checker": [
                {
                    "code": routing.holder.user_code if routing.holder else '',
                    "name": routing.holder.django_user.cnName if routing.holder else '',
                    "role": routing.holder.role.chinese_name if routing.holder else '',
                }  
            ]
        }
        
        result.append(routing_data)
    
    return result

def real_time_inventory_report_data_handing(data):
    """主要是把worker取最后一个, 如果最后一个是空则取倒数第二个"""

    for obj in data:
        del obj["due_date"]
        del obj["received_date"]
        del obj["site"]
        del obj["workorder"]
        # del obj["due_date"]
        del obj["design"]
        del obj["gold_type"]
        del obj["source"]

        worker_len = len(obj["worker"])
        if worker_len > 1:
            if obj["worker"][worker_len - 1]["name"]:
                obj["worker"] = obj["worker"][worker_len - 1]
            else:
                obj["worker"] = obj["worker"][worker_len - 2]
        else:
            obj["worker"] = obj["worker"][-1]
    
    print(data)
    return data